#ifndef CONDITIONVARIABLE_HPP_
# define CONDITIONVARIABLE_HPP_

# include <pthread.h>
# include "Mutex.hpp"
# include "Utils/macros.hpp"

namespace wrappers {
namespace pthread {

/*! \class ConditionVariable
 * \brief Wrapper for pthread condition variables
 *
 * Provide a mechanism for one thread to wait for notification from another
 * thread that a particular condition has become true.
 * Copies of this class cannot be made.
 */
class ConditionVariable {
public:
  /*! Default constructor */
  ConditionVariable();
  /*! Destructor */
  virtual ~ConditionVariable();

  /*! Unblock \b all threads blocked on the condition variable */
  virtual void NotifyAll();

  /*! Unblock \b one thread blocked on the condition variable */
  virtual void NotifyOne();

  /*! Call Mutex::Unlock() on \a lock and blocks the current thread. The thread
   * will unblock when notified by a call to NotifyOne() or NotifyAll(). When
   * the thread is unblocked, the lock is reacquired by invoking Mutex::Lock()
   * on lock before the call to Wait returns.
   * \param lock : The mutex to use in the \c pthread_cond_wait()
   */
  void Wait(Mutex &lock);

  /*! Same as Wait() but wait for a maximum time
   * \param lock : The mutex to use in the \c pthread_cond_wait()
   * \param timeOut : The maximum time to wait
   * \return true if the time specified by timeOut has passed, false otherwise
   */
  bool TimedWait(Mutex &lock, const struct timespec &timeOut);

  /*! Get the pthread_cond_t associated with this object
   * \return A reference on the associated pthread_cond_t
   */
  pthread_cond_t &GetCondition();

protected:
  /*! Disallow copy constructor and assignment operator */
  DISALLOW_COPY_AND_ASSIGN (ConditionVariable);

  pthread_cond_t mCondition; /*!< The pthread condition variable */
};

}
}

#endif /* !CONDITIONVARIABLE_HPP_ */
